package com.lizemin.multicache.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.cola.dto.MultiResponse;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.lizemin.multicache.entity.Employee;
import com.lizemin.multicache.service.CacheManager;
import com.lizemin.multicache.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author lzm
 * @date 2025/4/13 10:28
 * @description
 */
@RestController
public class EmployeeController {

    /**
     * 员工列表缓存key
     */
    public static final String EMPLOYEES_KEY = "employees";

    /**
     * 员工列表缓存过期时间，单位：分钟
     */
    public static final int EXPIRE_TIME = 5;

    @Autowired
    EmployeeService employeeService;

    @Autowired
    StringRedisTemplate redisTemplate;

    Cache<Object, Object> cache = Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(EXPIRE_TIME, TimeUnit.MINUTES)
            .build();

    @Autowired
    CacheManager cacheManager;

    /**
     * 查询员工列表(直接查询数据库)
     *
     * @return 员工列表
     */
    @GetMapping("/getEmployees/db")
    public MultiResponse<Employee> getEmployees() {
        List<Employee> employees = employeeService.list();
        return MultiResponse.ofWithoutTotal(employees);
    }

    /**
     * 查询员工列表(从redis缓存中查询)
     *
     * @return 员工列表
     */
    @GetMapping("/getEmployees/redis")
    public MultiResponse<Employee> getEmployeesFromRedis() {
        // 从redis缓存中查数据
        String cache = redisTemplate.opsForValue().get(EMPLOYEES_KEY);
        if (StrUtil.isNotBlank(cache)) {
            return MultiResponse.ofWithoutTotal(JSONUtil.toList(cache, Employee.class));
        }
        // 缓存中没有数据，从数据库查询并存入缓存
        List<Employee> employees = employeeService.list();
        if (CollectionUtil.isEmpty(employees)) {
            return MultiResponse.ofWithoutTotal(Collections.emptyList());
        }
        redisTemplate.opsForValue().set(EMPLOYEES_KEY, JSONUtil.toJsonStr(employees), EXPIRE_TIME, TimeUnit.MINUTES);
        return MultiResponse.ofWithoutTotal(employees);
    }

    /**
     * 查询员工列表(从本地缓存中查询数据)
     *
     * @return 员工列表
     */
    @GetMapping("/getEmployees/caffeine")
    public MultiResponse<Employee> getEmployeesFromCaffeine() {
        // 从caffeine缓存中查数据
        String localCache = (String) cache.getIfPresent(EMPLOYEES_KEY);
        if (StrUtil.isNotBlank(localCache)) {
            return MultiResponse.ofWithoutTotal(JSONUtil.toList(localCache, Employee.class));
        }
        List<Employee> employees = employeeService.list();
        if (CollectionUtil.isEmpty(employees)) {
            return MultiResponse.ofWithoutTotal(Collections.emptyList());
        }
        cache.put(EMPLOYEES_KEY, JSONUtil.toJsonStr(employees));
        return MultiResponse.ofWithoutTotal(employees);
    }

    /**
     * 从多级缓存中查询员工信息
     *
     * @return 员工列表
     */
    @GetMapping("/getEmployees/multiCache")
    public MultiResponse<Employee> getEmployeesFromMultiCache() {
        // 从缓存中查数据
        String cache = cacheManager.getCache(EMPLOYEES_KEY);
        if (StrUtil.isNotBlank(cache)) {
            return MultiResponse.ofWithoutTotal(JSONUtil.toList(cache, Employee.class));
        }
        // 缓存中没有，从数据库中查，然后放到缓存中
        List<Employee> employees = employeeService.list();
        if (CollectionUtil.isEmpty(employees)) {
            return MultiResponse.ofWithoutTotal(Collections.emptyList());
        }
        cacheManager.setCache(EMPLOYEES_KEY, JSONUtil.toJsonStr(employees));
        return MultiResponse.ofWithoutTotal(employees);
    }

}
